package me.itsoo.artemis.framework.core.render;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * SQL 高亮渲染器
 *
 * @author zxy
 * @version 0.0.1
 * @since 2023/6/1
 */
public class SqlHighlightRender implements Render {

    private static final Pattern PATTERN = Pattern.compile("(?msi)('(?:''|[^'])*')|(\"(?:\"\"|[^\"])*\")|--.*?$|/\\*.*?\\*/|\\b(ADD|ALL|ALTER|ANALYZE|AND|AS|ASC|ASENSITIVE|BEFORE|BETWEEN|BIGINT|BINARY|BLOB|BOTH|BY|CALL|CASCADE|CASE|CHANGE|CHAR|CHARACTER|CHECK|COLLATE|COLUMN|CONDITION|CONNECTION|CONSTRAINT|CONTINUE|CONVERT|CREATE|CROSS|CURRENT_DATE|CURRENT_TIME|CURRENT_TIMESTAMP|CURRENT_USER|CURSOR|DATABASE|DATABASES|DAY_HOUR|DAY_MICROSECOND|DAY_MINUTE|DAY_SECOND|DEC|DECIMAL|DECLARE|DEFAULT|DELAYED|DELETE|DESC|DESCRIBE|DETERMINISTIC|DISTINCT|DISTINCTROW|DIV|DOUBLE|DROP|DUAL|EACH|ELSE|ELSEIF|ENCLOSED|ESCAPED|EXISTS|EXIT|EXPLAIN|FALSE|FETCH|FLOAT|FLOAT4|FLOAT8|FOR|FORCE|FOREIGN|FROM|FULLTEXT|GOTO|GRANT|GROUP|HAVING|HIGH_PRIORITY|HOUR_MICROSECOND|HOUR_MINUTE|HOUR_SECOND|IF|IGNORE|IN|INDEX|INFILE|INNER|INOUT|INSENSITIVE|INSERT|INT|INT1|INT2|INT3|INT4|INT8|INTEGER|INTERVAL|INTO|IS|ITERATE|JOIN|KEY|KEYS|KILL|LABEL|LEADING|LEAVE|LEFT|LIKE|LIMIT|LINEAR|LINES|LOAD|LOCALTIME|LOCALTIMESTAMP|LOCK|LONG|LONGBLOB|LONGTEXT|LOOP|LOW_PRIORITY|MATCH|MEDIUMBLOB|MEDIUMINT|MEDIUMTEXT|MIDDLEINT|MINUTE_MICROSECOND|MINUTE_SECOND|MOD|MODIFIES|NATURAL|NOT|NO_WRITE_TO_BINLOG|NULL|NUMERIC|ON|OPTIMIZE|OPTION|OPTIONALLY|OR|ORDER|OUT|OUTER|OUTFILE|PRECISION|PRIMARY|PROCEDURE|PURGE|RAID0|RANGE|READ|READS|REAL|REFERENCES|REGEXP|RELEASE|RENAME|REPEAT|REPLACE|REQUIRE|RESTRICT|RETURN|REVOKE|RIGHT|RLIKE|SCHEMA|SCHEMAS|SECOND_MICROSECOND|SELECT|SENSITIVE|SEPARATOR|SET|SHOW|SMALLINT|SPATIAL|SPECIFIC|SQL|SQLEXCEPTION|SQLSTATE|SQLWARNING|SQL_BIG_RESULT|SQL_CALC_FOUND_ROWS|SQL_SMALL_RESULT|SSL|STARTING|STRAIGHT_JOIN|TABLE|TERMINATED|THEN|TINYBLOB|TINYINT|TINYTEXT|TO|TRAILING|TRIGGER|TRUE|UNDO|UNION|UNIQUE|UNLOCK|UNSIGNED|UPDATE|USAGE|USE|USING|UTC_DATE|UTC_TIME|UTC_TIMESTAMP|VALUES|VARBINARY|VARCHAR|VARCHARACTER|VARYING|WHEN|WHERE|WHILE|WITH|WRITE|X509|XOR|YEAR_MONTH|ZEROFILL)\\b");

    @Override
    public String doRend(String content) {
        final StringBuilder result = new StringBuilder();
        final Matcher m = PATTERN.matcher(content);

        int i;
        String c;
        for (i = 0; m.find(); i += c.length()) {
            c = m.group();
            result.append(content, i, (i = m.start()));
            // 值
            if (this.isValuesContent(c)) {
                this.rendHighlightValues(result, c);
            }
            // 注释
            else if (this.isCommentsContent(c)) {
                this.rendHighlightComments(result, c);
            }
            // 关键字
            else {
                this.rendHighlightKeywords(result, c);
            }
        }

        return result.append(content.substring(i)).toString();
    }

    private boolean isValuesContent(String c) {
        return c.startsWith("'") || c.startsWith("\"");
    }

    private boolean isCommentsContent(String c) {
        return c.startsWith("--") || c.startsWith("/*");
    }

    private void rendHighlightValues(StringBuilder sb, String c) {
        sb.append("<span style=\"color: #080; font-weight: bold;\">").append(c).append("</span>");
    }

    private void rendHighlightComments(StringBuilder sb, String c) {
        sb.append("<span style=\"color: #888; font-style: normal;\">").append(c).append("</span>");
    }

    private void rendHighlightKeywords(StringBuilder sb, String c) {
        sb.append("<span style=\"color: #04e; font-weight: bold;\">").append(c).append("</span>");
    }
}
